#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h> //posix网络编程
#include <strings.h>
#include <pthread.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include "../common/network/inc/Message.h"

typedef struct sockaddr_in sockaddr_in;
typedef struct sockaddr sockaddr;

typedef struct epoll_event epoll_event;

int main(int argc, char const *argv[])
{
    //1 创建socket文件描述符
    int serverFd = socket(AF_INET,SOCK_STREAM,0);
    if(serverFd == -1)
    {
        perror("创建套接字失败!");
        return -1;
    }

    //2 创建地址结构体对象
    sockaddr_in serverAddr;
    int addrSize = sizeof(sockaddr_in);
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(9999);
    serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);

    //3 将地址和文件描述符做绑定
    int retVal = bind(serverFd,(sockaddr*)&serverAddr,addrSize);
    if(retVal == -1)
    {
        perror("绑定失败!");
        return -1;
    }

    //4 监听
    retVal = listen(serverFd,10);
    if(retVal == -1)
    {
        perror("监听失败!");
        return -1;
    }

    // 创建epoll实例
    int epollId = epoll_create(100);
    if(epollId == -1)
    {
        perror("epoll创建失败");
        return -1;
    }

    epoll_event event;
    event.events = EPOLLIN;
    event.data.fd = serverFd;
    // 将serverFd加入到epoll实例中
    epoll_ctl(epollId,EPOLL_CTL_ADD,serverFd,&event);
    
    // 定义一个数组来接收
    epoll_event evs[1024]; 
    //5 接收请求,建立连接
    while (1)
    {
        int ret = epoll_wait(epollId,evs,1024,3000);
        if(ret == -1)
        {
            perror("epoll失败!");
            continue;
        }else if(ret == 0)
        {
            continue;
        }
        for(int i=0;i<ret;i++)
        {
            int fd = evs[i].data.fd;
            if(serverFd == fd)
            {
                sockaddr_in clientAddr;
                int clientFd = accept(serverFd,(sockaddr*)&clientAddr,&addrSize);


                printf("%s:%d connected......\n",inet_ntoa(clientAddr.sin_addr),ntohs(clientAddr.sin_port));
                // 将通信描述符添加到epoll中
                epoll_event event;
                event.data.fd = clientFd;
                event.events = EPOLLIN; 
                epoll_ctl(epollId,EPOLL_CTL_ADD,clientFd,&event);
                continue;
            }

            if(evs[i].events & EPOLLOUT)
            {
                continue;
            }
            
            Message *msg = receiveMessage(fd);
            printf("receiver data:length=%d,contentType=%d,content=%s\n",msg->length,msg->type,msg->content);
            int len = msg->length;
            if(len == -1)
            {
                perror("read error....");
            }else if(len == 0)
            {
                printf("client close...\n");
                close(fd);
                
                epoll_ctl(epollId,EPOLL_CTL_DEL,fd,NULL);
            } else
            {
                int size = sendMessage(fd,msg);
                printf("服务端发送消息成功,size=%d\n",size);
            }
            free(msg);
        }
    }
    
    
    //7 关闭文件描述符
    close(serverFd);
    return 0;
}
